/*--------------------------------------------------------------------------------------*\
**
** quest_log_window.cpp
**
** Heroes IV
** Copyright 2001, The 3DO Company
**
\*--------------------------------------------------------------------------------------*/

// kill the 255+ character identifier warning.  Templates tend to exceed that easily.
#include "precompiled.h"
#pragma warning( disable: 4786 )

#include "quest_log_window.h"

#include "adaptor_handler.h"
#include "adv_keymaster_tent.h"
#include "adventure_frame.h"
#include "adventure_map.h"
#include "adventure_map_window.h"
#include "bitmap_group.h"
#include "bitmap_group_cache.h"
#include "bitmap_layer_cache_window.h"
#include "bound_handler.h"
#include "button.h"
#include "button_cache.h"
#include "external_string.h"
#include "format_string.h"
#include "interface_help.h"
#include "kingdom_overview_window.h"
#include "player.h"
#include "quest_site.h"
#include "quest_site_list.h"
#include "scrollbar.h"
#include "standard_fonts.h"
#include "text_window.h"

extern t_button_cache			    g_ok_button;

namespace 
{ // unnamed namespace

    t_bitmap_group_cache        k_quest_log_bitmaps ("dialog.quest_log");
    t_external_string const k_text_title ( "quest_log_title.misc" );

	int const k_max_windows = 3;
}

t_quest_log_window::t_quest_log_window( t_window* parent, t_adventure_frame *frame_ptr )
                   : t_window( k_completely_transparent, parent )
{
    m_frame = frame_ptr;
    m_map = frame_ptr->get_map();
	m_bitmaps_ptr = k_quest_log_bitmaps.get();

	t_screen_rect rect;

	/*
    ** Create background bitmap.
    */
	t_bitmap_layer const*   layer;
	t_window*               background;
	t_window*               window_ptr;
	t_screen_point          origin(0,0);

	layer = m_bitmaps_ptr->find( "background" );
	background = new t_bitmap_layer_window( layer, origin, this );
	layer = m_bitmaps_ptr->find( "title_scroll" );
	window_ptr = new t_bitmap_layer_window( layer, origin, this );

    // Set position.
	t_screen_rect parent_rect;
    parent_rect = get_parent()->get_client_rect();
	rect = m_bitmaps_ptr->get_rect();
	rect += (parent_rect.size() - rect.size()) / 2;
	init( rect );

	// Add buttons.
	t_button* button_ptr;
	t_help_block const& shared_help_block = get_help_block( "shared" );

    rect = m_bitmaps_ptr->find( "close_button" )->get_rect();
	button_ptr = new t_button( g_ok_button.get(), rect.top_left(), this );
	button_ptr->set_click_handler( bound_handler( *this, &t_quest_log_window::close_clicked ));
	set_help( button_ptr, shared_help_block, "ok" );

    // Text windows.
    t_text_window*  text_window_ptr;

	rect = m_bitmaps_ptr->find( "title" )->get_rect();
	text_window_ptr  = new t_text_window( get_font( rect.height() ), rect, this, "", t_pixel_24(0,0,0) );
    text_window_ptr->set_text ( k_text_title );
	text_window_ptr->set_center_horizontal();

	gather_data();
    create_quests_windows();
    show_quests( 0 );
}

void t_quest_log_window::gather_data()
{
    t_player const &			player			= m_map->get_current_player();
    t_quest_site_list const &	quest_site_list	= player.get_quest_origin_sites();

	// Get the data for all the real quests
    for (int i=0; i<quest_site_list.size(); i++)
    {
		t_quest_entry	new_entry;

		new_entry.text		= quest_site_list[i]->get_quest_log_entry().c_str();
		new_entry.location	= quest_site_list[i]->get_position();

		m_data.push_back( new_entry );
    }

	// Now add entries for any visited keymaster huts
	for ( int object_id = m_map->get_first_object_id(); 
		  object_id != t_abstract_adventure_map::k_invalid_object_id; 
		  object_id = m_map->get_next_object_id( object_id ) ) 
	{
		t_adventure_object const * object = &m_map->get_adv_object( object_id );
		assert( object );

		// See if this is a keymaster's tent
		t_adv_keymaster_tent const * keymaster = dynamic_cast<t_adv_keymaster_tent const*>(object);
		if ( keymaster && player.has_key( keymaster->get_guard_color() ) ) 
		{
			t_quest_entry	new_entry;

			new_entry.text		= keymaster->get_name().c_str();
			new_entry.location	= keymaster->get_position();

			m_data.push_back( new_entry );
		}
    }
}

void t_quest_log_window::create_quests_windows()
{
	t_screen_rect           rect;
    t_screen_point          text_background_offset;
    t_screen_point          background_offset;
    t_screen_point          mini_map_offset;
    t_screen_point          frame_offset;
	t_screen_point          origin(0,0);
    t_screen_point          point;
	t_window_ptr            window_ptr;
	t_text_window*          text_window_ptr;
	t_bitmap_layer const*   layer;
	t_bitmap_layer*         exit_marker = m_bitmaps_ptr->find( "marker" );
	std::string             name;
    int i;

	rect = exit_marker->get_rect();
	exit_marker->offset( -rect.top_left() );

	t_bitmap_layer const* text_background = m_bitmaps_ptr->find( "text_background" );
    background_offset = text_background->get_rect().top_left() -
		            m_bitmaps_ptr->find( "quest_1" )->get_rect().top_left();
   	background_offset -= m_bitmaps_ptr->find( "text_background" )->get_rect().top_left();
    
    text_background_offset = m_bitmaps_ptr->find( "quest_text" )->get_rect().top_left() -
		            m_bitmaps_ptr->find( "quest_1" )->get_rect().top_left();
    
	layer = m_bitmaps_ptr->find( "frame" );
	m_map_frame = new t_bitmap_layer_window( layer, t_screen_point(0, 0), this );
    m_map_frame->set_visible( false );

    frame_offset = layer->get_rect().top_left() -
		            m_bitmaps_ptr->find( "quest_1" )->get_rect().top_left();
    mini_map_offset = m_bitmaps_ptr->find( "mini_map" )->get_rect().top_left() -
		            m_bitmaps_ptr->find( "quest_1" )->get_rect().top_left();
    
    i=0;
    while ((i<m_data.size()) && (i<k_max_windows))
    {
        i++;
        // Create background layer for text window.
		name = format_string( "quest_%i", i );
        origin = m_bitmaps_ptr->find( name )->get_rect().top_left();
        point = origin + background_offset;
	    window_ptr = new t_bitmap_layer_window( text_background, point, this );

        // Create text window.
        point = origin + text_background_offset;

        rect = m_bitmaps_ptr->find( "quest_text" )->get_rect();
        rect -= m_bitmaps_ptr->find( "quest_text" )->get_rect().top_left();
        rect += point;

	    text_window_ptr = new t_text_window( get_font( 20 ), rect, this, "", t_pixel_24(0,0,0) );
    	text_window_ptr->set_center_horizontal();

	    m_text_window_list.push_back( text_window_ptr );

        // Frame points.
        t_screen_point mini_map_point;
        t_screen_point frame_point;

        mini_map_point = origin + mini_map_offset;
        frame_point = origin + frame_offset;

        // Create button holder for mini-map.
        t_button *      map_button_ptr;
		map_button_ptr = new t_button( mini_map_point, this );
        
        // Create mini-map.
	    t_center_map_window *   mini_map_ptr;

        rect = m_bitmaps_ptr->find( "mini_map" )->get_rect();
        rect -= rect.top_left();
        mini_map_ptr = new t_center_map_window( *m_map, rect, m_frame->get_map_window(),
	    		                                map_button_ptr );

	    map_button_ptr->enable( true );
	    map_button_ptr->update_size();
	    map_button_ptr->set_click_handler( add_2nd_argument( bound_handler( *this, &t_quest_log_window::mini_map_clicked ), (i - 1)));
        m_map_button_list.push_back( map_button_ptr );
	    m_mini_map_list.push_back( mini_map_ptr );
       
        // Frame window.
	    layer = m_bitmaps_ptr->find( "frame" );
    	window_ptr = new t_bitmap_layer_window( layer, frame_point-layer->get_rect().top_left(), this );
        //m_screen_frame_points.push_back( frame_point );

        // Create teleporter exit marker.
    	window_ptr = new t_bitmap_layer_window( exit_marker, t_screen_point(0,0), mini_map_ptr );
        m_marker_window_list.push_back ( window_ptr );
    }

    // Create scrollbar.
    if ( m_data.size() > k_max_windows )
    {
        int scrollbar_limit = 0;
        scrollbar_limit = m_data.size() - k_max_windows;

	    rect = m_bitmaps_ptr->find( "scrollbar" )->get_rect();
    	m_scrollbar = new t_scrollbar( rect.top_left(), rect.height(), this, 0, 0, true );
    	m_scrollbar->set_position( 0 );
    	m_scrollbar->set_handler( bound_handler( *this, &t_quest_log_window::scrollbar_move));
    	m_scrollbar->set_limits( 0, scrollbar_limit );
    }

    m_current_quest_index = 0;
}

/*
** Show the visible entries in the list.
*/
void t_quest_log_window::show_quests( int start_index )
{
    int i=0;
    int window_index = start_index;
	t_screen_rect rect;

    if (!(m_data.size()))
        return;
    
    t_center_map_window *   mini_map_ptr = m_mini_map_list[ 0 ];

    while ((window_index<m_data.size()) && (i<k_max_windows))
    {
        // Set text.
	    m_text_window_list[i]->set_text( m_data[window_index].text );

        // Set marker position in mini-map.
	    m_mini_map_list[ i ]->set_view_level( m_data[window_index].location.level );
        
        rect = mini_map_ptr->get_tile_rect( m_data[window_index].location );
        m_marker_window_list[ i ]->move( rect.top_left() );

        i++;
        window_index++;
    }
}

void t_quest_log_window::scrollbar_move( t_scrollbar* scrollbar, int value )
{
    m_current_quest_index = value;
    show_quests( value );
}

void t_quest_log_window::mini_map_clicked( t_button* button_ptr, int index )
{


    // Center frame on quest.
	t_screen_point screen_point = m_map->get_screen_point( m_data[m_current_quest_index + index].location );

	t_adventure_map_window *    map_window_ptr = m_map->get_map_window();
	map_window_ptr->center_view( screen_point );
}

void t_quest_log_window::close_clicked( t_button* button_ptr )
{
    close();    
}

